#!/usr/local/bin/python2.7
import os, pickle, copy

from constants import *

class DBase(object):
    def __init__(self):
        self._components = []
        self._path = Constants.logs_dir
        self._name = Constants.dbase_name
        self._temp_name = 'temp-db.pickle'

        self._checks = []
        
    def addComponent(self, component):
        self._components.append(component)

    def addComponents(self, components):
        self._components.extend(components)

    def save(self):
        if isinstance(self._components, list):
            filepath = os.path.join(self._path, self._temp_name)
            with open(filepath, 'w') as myfile:
                pickle.dump(self._components, myfile)

            self._validatePickle()

    def _validatePickle(self):
        filepath = os.path.join(self._path, self._temp_name)
        old_path = os.path.join(self._path, self._name)

        try:
            with open(filepath, 'r') as myfile:
                components = pickle.load(myfile)
        except:
            os.remove(filepath)
        else:
            if os.path.isfile(old_path):

                os.remove(old_path)
            os.rename(filepath, old_path)

    def load(self):
        filepath = os.path.join(self._path, self._name)
        if os.path.isfile(filepath):
            with open(filepath, 'r') as myfile:
                self._components = pickle.load(myfile)
        else:
            self._components = []

    def getComps(self):
        return copy.deepcopy(self._components)
    components = property(getComps)

    def getCompRefs(self):
        return self._components
    ref_components = property(getCompRefs)

    def getProblems(self):
        self._buildChecks()
        invalids = {}
        for check in self._checks:
            invalids[check.field] = []

        # insert code that runs all checks and tallies failures
        for comp in self._components:
            for check in self._checks:
                if not check.isComponentValid(comp):
                    invalids[check.field].append(comp)

        return invalids
    problems = property(getProblems)


    def __str__(self):
        mystr = 'This database\'s characteristics:\n\n'
        mystr += 'Contains ' + str(len(self._components)) + ' entries.\n'
        mystr += 'Contains other interesting info.\n'
        mystr += '\n'
        mystr += 'Problems:'
        mystr += '\n'

        for prob, bad_comps in self.problems.items():
            mystr += '    '
            mystr += prob + ': ' + str(len(bad_comps)) + ' items'

            #for comp in bad_comps:
            #    mystr += '        '
            #    mystr += comp.name
            #    mystr += '\n'

            mystr += '\n'

        return mystr

    def _buildChecks(self):
        self._checks = []
        keys = ['SystemName', 'SystemNumber', 'UniqueIDNumber', \
                'ItemName', 'BuildingNumber', 'Location', 'Drawings', \
                'CriticalComponent']

        for key in keys:
            check = DontWantBlankCheck('gen', key)
            self._checks.append(check)

        check = WantBlankCheck('gen', 'Comments')
        self._checks.append(check)

class CompCheck(object):

    def __init__(self, dict_name, key):
        
        self.dict_name = dict_name
        self.key = key

    def isComponentValid(self, comp):
        pass

    def getMyField(self):
        return self.dict_name + '_' + self.key
    field = property(getMyField)

class DontWantBlankCheck(CompCheck):
    def __init__(self, dict_name, key):
        CompCheck.__init__(self, dict_name, key)

    def isComponentValid(self, comp):
        des_dict = comp.getDict(self.dict_name)
        vals = des_dict[self.key]

        valid = False
        for val in vals:
            text = val.strip().lower()

            if len(text) > 0:
                valid = True

        return valid

class WantBlankCheck(CompCheck):
    def __init__(self, dict_name, key):
        CompCheck.__init__(self, dict_name, key)

    def isComponentValid(self, comp):
        des_dict = comp.getDict(self.dict_name)
        vals = des_dict[self.key]

        valid = True
        for val in vals:
            text = val.strip().lower()

            if len(text) > 0:
                valid = False

        return valid

